import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.Timer;

public class SnakeGame {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new StartScreen());
    }
}

class StartScreen extends JFrame {
    public StartScreen() {
        setTitle("贪吃蛇游戏");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);

        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(Color.BLACK);

        JLabel title = new JLabel("贪吃蛇游戏", SwingConstants.CENTER);
        title.setFont(new Font("微软雅黑", Font.BOLD, 50));
        title.setForeground(Color.GREEN);

        JButton startButton = new JButton("开始游戏");
        startButton.setFont(new Font("微软雅黑", Font.PLAIN, 30));
        startButton.addActionListener(e -> {
            new GameWindow();
            dispose();
        });

        panel.add(title, BorderLayout.CENTER);
        panel.add(startButton, BorderLayout.SOUTH);

        add(panel);
        pack();
        setSize(600, 600);
        setLocationRelativeTo(null);
        setVisible(true);
    }
}

class GameWindow extends JFrame {
    public GameWindow() {
        setTitle("贪吃蛇游戏");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        add(new GamePanel());
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }
}

class GamePanel extends JPanel implements ActionListener, KeyListener {
    private static final int WIDTH = 600;       // 游戏区域宽度
    private static final int HEIGHT = 600;      // 游戏区域高度
    private static final int UNIT_SIZE = 25;    // 每个游戏单位的大小(像素)
    private static final int DELAY = 150;       // 游戏刷新间隔(毫秒)

    private final ArrayList<Point> snake;      // 蛇身坐标集合
    private Point food;                        // 食物坐标
    private char direction = 'R';              // 当前移动方向(R右/L左/U上/D下)
    private boolean running = false;            // 游戏运行状态
    private Timer timer;                        // 游戏定时器
    private int score = 0;                      // 当前得分

    public GamePanel() {
        snake = new ArrayList<>();
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        setBackground(Color.BLACK);
        setFocusable(true);
        addKeyListener(this);
        startGame();
    }

    //游戏初始化
    public void startGame() {
        snake.clear();  // 清空蛇身
        snake.add(new Point(WIDTH/2, HEIGHT/2)); // 初始蛇头在中心
        direction = 'R'; // 初始向右移动
        score = 0;      // 重置分数
        spawnFood();    // 生成食物
        running = true; // 设置运行状态

        // 创建定时器任务
        timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                if (running) {
                    move();         // 移动蛇
                    checkCollision(); // 检测碰撞
                }
                repaint(); // 重绘界面
            }
        }, DELAY, DELAY); // 初始延迟和周期都是DELAY
    }

    public void spawnFood() {
        Random random = new Random();
        int x = random.nextInt(WIDTH / UNIT_SIZE) * UNIT_SIZE;
        int y = random.nextInt(HEIGHT / UNIT_SIZE) * UNIT_SIZE;
        food = new Point(x, y);
    }

    public void move() {
        // 获取当前蛇头
        Point head = snake.get(0);
        // 创建新蛇头(根据方向移动)
        Point newHead = new Point(head);

        // 根据方向计算新蛇头位置
        switch(direction) {
            case 'U': newHead.y -= UNIT_SIZE; break; // 上移
            case 'D': newHead.y += UNIT_SIZE; break; // 下移
            case 'L': newHead.x -= UNIT_SIZE; break; // 左移
            case 'R': newHead.x += UNIT_SIZE; break; // 右移
        }

        // 添加新蛇头
        snake.add(0, newHead);

        // 检查是否吃到食物
        if (newHead.equals(food)) {
            score++;        // 增加分数
            spawnFood();    // 生成新食物
        } else {
            // 没吃到食物则移除蛇尾
            snake.remove(snake.size() - 1);
        }
    }

    public void checkCollision() {
        Point head = snake.get(0);

        // 撞墙检测
        if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) {
            running = false;
        }

        // 自撞检测
        for (int i = 1; i < snake.size(); i++) {
            if (head.equals(snake.get(i))) {
                running = false;
                break;
            }
        }

        // 游戏结束处理
        if (!running) {
            timer.cancel(); // 停止定时器
            repaint();      // 重绘游戏结束画面
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        if (running) {
            // 绘制食物(红色圆形)
            g.setColor(Color.RED);
            g.fillOval(food.x, food.y, UNIT_SIZE, UNIT_SIZE);

            // 绘制蛇身(绿色方块)
            for (Point p : snake) {
                g.setColor(Color.GREEN);
                g.fillRect(p.x, p.y, UNIT_SIZE, UNIT_SIZE);
            }

            // 绘制分数和长度信息
            g.setColor(Color.WHITE);
            g.setFont(new Font("微软雅黑", Font.BOLD, 20));
            g.drawString("分数: " + score, 20, 20);
            g.drawString("长度: " + snake.size(), 150, 20);
        } else {
            gameOver(g); // 游戏结束画面
        }
    }

    public void gameOver(Graphics g) {
        // 游戏结束文字
        g.setColor(Color.RED);
        g.setFont(new Font("微软雅黑", Font.BOLD, 50));
        g.drawString("游戏结束", 150, HEIGHT/2 - 50);

        // 最终统计
        g.setColor(Color.WHITE);
        g.setFont(new Font("微软雅黑", Font.BOLD, 30));
        g.drawString("最终分数: " + score, 200, HEIGHT/2);
        g.drawString("蛇的长度: " + snake.size(), 200, HEIGHT/2 + 50);

        // 重新开始提示
        g.setFont(new Font("微软雅黑", Font.PLAIN, 20));
        g.drawString("按空格键重新开始", 200, HEIGHT/2 + 100);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (running) {
            move();
            checkCollision();
        }
        repaint();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()) {
            case KeyEvent.VK_UP:
                if (direction != 'D') direction = 'U'; // 不能直接反向
                break;
            case KeyEvent.VK_DOWN:
                if (direction != 'U') direction = 'D';
                break;
            case KeyEvent.VK_LEFT:
                if (direction != 'R') direction = 'L';
                break;
            case KeyEvent.VK_RIGHT:
                if (direction != 'L') direction = 'R';
                break;
            case KeyEvent.VK_SPACE:
                if (!running) startGame(); // 空格重新开始
                break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {}

    @Override
    public void keyTyped(KeyEvent e) {}
}